package edu.usc.tweetool.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import edu.usc.tweetool.hibernate.UserTheta;

public class CalTool {

	public static final boolean MODE_DISTANCE = true;
	public static final boolean MODE_ANGLE = false;
	public static final double SUM_VAR = 0.4;
	public static final double DEM_VAR = 0.6;

	public static UserTheta getSumUserTheta(UserTheta owner,
			List<UserTheta> followings) {
		double[] init = getFloatList(owner);
		double[] sum = new double[13];
		for (int i = 0; i < sum.length; i++) {
			sum[i] = 0.0;
		}
		for (int i = 0; i < followings.size(); i++) {
			double[] more = getFloatList(followings.get(i));
			for (int j = 0; j < sum.length; j++) {
				sum[j] += more[j];
			}
		}
		for (int i = 0; i < sum.length; i++) {
			sum[i] = sum[i] / followings.size() * DEM_VAR + init[i] * SUM_VAR;
		}
		return new UserTheta(owner.getUserId(), sum[0], sum[1], sum[2], sum[3],
				sum[4], sum[5], sum[6], sum[7], sum[8], sum[9], sum[10],
				sum[11], sum[12]);
	}

	public static UserTheta[] getClosest(UserTheta ut, List<UserTheta> uts,
			boolean mode, int size) {
		UserTheta[] uta = new UserTheta[uts.size()];
		uts.toArray(uta);
		Double[] results = new Double[uts.size()];
		for (int i = 0; i < uts.size(); i++) {
			if (mode) {
				results[i] = getDistance(ut, uta[i]);
			} else {
				results[i] = getAngle(ut, uta[i]);
			}
		}

		for (int i = 0; i < uta.length - 1; i++) {
			for (int j = i + 1; j < uta.length; j++) {
				if (results[i] > results[j]) {
					UserTheta tempUT = uta[i];
					uta[i] = uta[j];
					uta[j] = tempUT;
					Double tr = results[i];
					results[i] = results[j];
					results[j] = tr;
				}
			}
		}
		System.out.println("mode: " + mode);
		UserTheta[] uto = new UserTheta[size];
		for (int i = 0; i < size; i++) {
			System.out.println("UserID: " + uta[i]
					+ " Results:" + results[i]);
			uto[i] = uta[i];
		}
		return uto;
	}

	public static double getDistance(UserTheta uta, UserTheta utb) {
		if(uta == utb){
			return 9999;
		}
		double[] al = getFloatList(uta);
		double[] bl = getFloatList(utb);
		double sum = 0.0;
		for (int i = 0; i < al.length; i++) {
			sum += (al[i] - bl[i]) * (al[i] - bl[i]);
		}
		return Math.sqrt(sum);
	}

	public static double getAngle(UserTheta uta, UserTheta utb) {
		if(uta == utb){
			return 9999;
		}
		double[] al = getFloatList(uta);
		double[] bl = getFloatList(utb);
		double nj = 0.0;
		double sa = 0.0;
		double sb = 0.0;
		for (int i = 0; i < al.length; i++) {
			nj += al[i] * bl[i];
			sa += al[i] * al[i];
			sb += bl[i] * bl[i];
		}
		return Math.acos(nj / (Math.sqrt(sa) * Math.sqrt(sb)));
	}

	public static UserTheta[] getTops(List<UserTheta> uts, int mode) {
		UserTheta[] uto = new UserTheta[10];
		Collections.sort(uts, new SortBy(mode));
		// System.err.println(mode);
		for (int i = 0; i < uto.length; i++) {
			uto[i] = uts.get(uts.size() - i - 1);
		}
		return uto;
	}

	private static void swap(UserTheta uta, UserTheta utb) {
		UserTheta temp = uta;
		uta = utb;
		utb = temp;
	}

	/*
	 * public static boolean compareUT(UserTheta uta, UserTheta utb, int mode) {
	 * if (utb == null) { return true; } if (mode == 0) return
	 * uta.getArtDesign() > utb.getArtDesign(); else if (mode == 1) return
	 * uta.getBooks() > utb.getBooks(); else if (mode == 2) return
	 * uta.getBusiness() > utb.getBusiness(); else if (mode == 3) return
	 * uta.getCharity() > utb.getCharity(); else if (mode == 4) return
	 * uta.getEntertainment() > utb.getEntertainment(); else if (mode == 5)
	 * return uta.getFamily() > utb.getFamily(); else if (mode == 6) return
	 * uta.getFashion() > utb.getFashion(); else if (mode == 7) return
	 * uta.getFoodDrink() > utb.getFoodDrink(); else if (mode == 8) return
	 * uta.getHealth() > utb.getHealth(); else if (mode == 9) return
	 * uta.getMusic() > utb.getMusic(); else if (mode == 10) return
	 * uta.getNews() > utb.getNews(); else if (mode == 11) return
	 * uta.getScienTech() > utb.getScienTech(); else if (mode == 12) return
	 * uta.getSports() > utb.getSports(); return false; }
	 */
	public static double[] getFloatList(UserTheta ut) {
		double[] list = new double[13];
		list[0] = ut.getArtDesign();
		list[1] = ut.getBooks();
		list[2] = ut.getBusiness();
		list[3] = ut.getCharity();
		list[4] = ut.getEntertainment();
		list[5] = ut.getFamily();
		list[6] = ut.getFashion();
		list[7] = ut.getFoodDrink();
		list[8] = ut.getHealth();
		list[9] = ut.getMusic();
		list[10] = ut.getNews();
		list[11] = ut.getScienTech();
		list[12] = ut.getSports();
		return list;
	}
}

class SortBy implements Comparator<UserTheta> {

	private int mode;

	public SortBy(int mode) {
		this.mode = mode;
		System.out.println("Compare Mode" + mode);
	}

	@Override
	public int compare(UserTheta uta, UserTheta utb) {
		if (mode == 0) {
			return uta.getArtDesign().compareTo(utb.getArtDesign());
		} else if (mode == 1) {

			return uta.getBooks().compareTo(utb.getBooks());
		} else if (mode == 2) {
			return uta.getBusiness().compareTo(utb.getBusiness());
		} else if (mode == 3) {
			return uta.getCharity().compareTo(utb.getCharity());
		} else if (mode == 4) {
			return uta.getEntertainment().compareTo(utb.getEntertainment());
		} else if (mode == 5) {
			return uta.getFamily().compareTo(utb.getFamily());
		} else if (mode == 6) {
			return uta.getFashion().compareTo(utb.getFashion());
		} else if (mode == 7) {
			return uta.getFoodDrink().compareTo(utb.getFoodDrink());
		} else if (mode == 8) {
			return uta.getHealth().compareTo(utb.getHealth());
		} else if (mode == 9) {
			return uta.getMusic().compareTo(utb.getMusic());
		} else if (mode == 10) {
			return uta.getNews().compareTo(utb.getNews());
		} else if (mode == 11) {
			return uta.getScienTech().compareTo(utb.getScienTech());
		} else if (mode == 12) {
			return uta.getSports().compareTo(utb.getSports());
		}
		return 0;
	}
}
